package com.mida.app.knw.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.mida.app.knw.service.DetailCodingSystemService;
import com.mida.app.knw.service.KnwNoumenonService;
import com.mida.app.knw.service.MdmService;
import com.mida.dms.knw.api.KnwNoumenonApi;
import com.mida.dms.knw.entity.KnwNoumenon;
import com.mida.dms.knw.entity.KnwNoumenonUserSpace;
import com.mida.dms.knw.entity.vo.KnwNoumenonPage;
import com.mida.dms.knw.entity.vo.KnwNoumenonRelationVo;
import com.mida.dms.knw.entity.vo.KnwNoumenonTreeVo;
import com.mida.dms.knw.vo.*;
import com.mida.dms.mdm.dto.UserDto;
import com.mida.dms.mdm.pojo.auto.MsdDataSet;
import com.mida.tool.common.result.ActionResult;
import com.mida.tool.common.result.ListResult;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.mida.tool.common.result.BaseResult.*;
import static com.mida.tool.common.result.BaseResult.buildActionSuccess;

/**
 * <h1></h1>
 * <p>
 *
 * </p>
 *
 * @author jian.li on 2021/6/21 17:47
 */
@Service
@Slf4j
public class KnwNoumenonServiceImpl implements KnwNoumenonService {

    @Autowired
    private KnwNoumenonApi knwNoumenonApi;
    @Autowired
    private DetailCodingSystemService detailCodingSystemService;
    @Autowired
    private MdmService mdmService;

    @Override
    public ActionResult add(KnwNoumenonVo knwNoumenonVo) {
        return knwNoumenonApi.add(knwNoumenonVo);
    }

    @Override
    public ActionResult delete(Long soid) {
        return knwNoumenonApi.delete(soid);
    }

    @Override
    public ActionResult update(KnwNoumenonVo knwNoumenonVo) {
        return knwNoumenonApi.update(knwNoumenonVo);
    }

    @Override
    public ActionResult checkName(Long originalSoid, Long newNoumenonType, Long newNoumenonSubType, String newNoumenonShowName) {
        return knwNoumenonApi.checkDataRepeat(originalSoid, newNoumenonType, newNoumenonSubType, newNoumenonShowName);
    }

    @Override
    public ListResult<com.mida.dms.knw.entity.vo.KnwNoumenonVo> get(Long soid) {
        ListResult<com.mida.dms.knw.entity.vo.KnwNoumenonVo> listResult = new ListResult<com.mida.dms.knw.entity.vo.KnwNoumenonVo>();

        ListResult<com.mida.dms.knw.entity.vo.KnwNoumenonVo> knwNoumenonVoListResult = null;
        try {
            knwNoumenonVoListResult = knwNoumenonApi.get(soid);
            if (ObjectUtils.isNotEmpty(knwNoumenonVoListResult) && ObjectUtils.isNotEmpty(knwNoumenonVoListResult.getData())) {
                com.mida.dms.knw.entity.vo.KnwNoumenonVo data = knwNoumenonVoListResult.getData();
                if (ObjectUtils.isNotEmpty(data) && ObjectUtils.isNotEmpty(data.getNoumenonSubType()) && ObjectUtils.isNotEmpty(data.getNoumenonType())) {
                    Long noumenonSubType = data.getNoumenonSubType();
                    Long noumenonType = data.getNoumenonType();
                    //设置本体二级类型名称
                    String dataSetMeaningSub = null;
                    MsdDataSet conceptSoidByDataSetSoidSub = detailCodingSystemService.getConceptSoidByDataSetSoid(noumenonSubType);
                    if (ObjectUtils.isNotEmpty(conceptSoidByDataSetSoidSub)) {
                        dataSetMeaningSub = conceptSoidByDataSetSoidSub.getDataSetMeaning();
                        data.setNoumenonSubTypeName(dataSetMeaningSub);
                    }
                    //设置本体一级类型名称
                    String dataSetMeaning = null;
                    MsdDataSet conceptSoidByDataSetSoid1 = detailCodingSystemService.getConceptSoidByDataSetSoid(noumenonType);
                    if (ObjectUtils.isNotEmpty(conceptSoidByDataSetSoid1)) {
                        dataSetMeaning = conceptSoidByDataSetSoid1.getDataSetMeaning();
                        data.setNoumenonTypeName(dataSetMeaning);
                    }
                    //分页最终显示类型
                    data.setPageTypeName(dataSetMeaning + "|" + dataSetMeaningSub);
                }
            }
        } catch (Exception e) {
            log.error("查询本体发送异常: ", e);
            buildListWarn(listResult, "查询本体失败");
        }
        return knwNoumenonVoListResult;
    }

    @Override
    public ListResult<PageResultVo<com.mida.dms.knw.entity.vo.KnwNoumenonVo>> findPage(KnwNoumenonPageVo vo) {
        ListResult result = new ListResult();
        ListResult<PageResultVo<com.mida.dms.knw.entity.vo.KnwNoumenonVo>> page = null;
        try {
            page = knwNoumenonApi.findPage(vo);
            if (ObjectUtils.isEmpty(page) || ObjectUtils.isEmpty(page.getData())) {
                buildListWarn(result, "本体分页查询为空");
                return result;
            }
            PageResultVo<com.mida.dms.knw.entity.vo.KnwNoumenonVo> data = page.getData();
            if (ObjectUtils.isNotEmpty(data) && ObjectUtils.isNotEmpty(data.getPage())) {
                Page page1 = data.getPage();
                if (ObjectUtils.isNotEmpty(page1) && ObjectUtils.isNotEmpty(page1.getTotalCount())) {
                    Integer totalCount = page1.getTotalCount();
                    if (totalCount > 1) {
                        List<com.mida.dms.knw.entity.vo.KnwNoumenonVo> list = data.getList();
                        List<Long> noumenonTypes = list.stream().filter(e -> ObjectUtils.isNotEmpty(e.getNoumenonType())).map(knwNoumenonVo -> knwNoumenonVo.getNoumenonType()).collect(Collectors.toList());
                        List<Long> noumenonSubTypes = list.stream().filter(e -> ObjectUtils.isNotEmpty(e.getNoumenonSubType())).map(knwNoumenonVo -> knwNoumenonVo.getNoumenonSubType()).collect(Collectors.toList());
                        Map<Long, String> dataSetNameMap = detailCodingSystemService.getDataSetNameMap(noumenonTypes);
                        Map<Long, String> dataSetNameMapSub = detailCodingSystemService.getDataSetNameMap(noumenonSubTypes);
                        list.stream().filter(knwNoumenonVo -> ObjectUtils.isNotEmpty(knwNoumenonVo)).forEach(knwNoumenonVo -> {
                            String dataSetMeaning = dataSetNameMap.get(knwNoumenonVo.getNoumenonType());
                            String dataSetMeaningSub = dataSetNameMapSub.get(knwNoumenonVo.getNoumenonSubType());
                            knwNoumenonVo.setNoumenonTypeName(dataSetMeaning);
                            knwNoumenonVo.setNoumenonSubTypeName(dataSetMeaningSub);
                            knwNoumenonVo.setPageTypeName(dataSetMeaning + "|" + dataSetMeaningSub);
                        });
                    }
                }
            }
        } catch (Exception e) {
            log.error("分页查询本体发送异常", e);
            buildListWarn(result, "分页查询本体失败");
        }
        return page;
    }

    @Override
    public ListResult<List<com.mida.dms.knw.entity.vo.KnwNoumenonVo>> findAll(String search) {
        ListResult listResult = new ListResult();

        ListResult<List<com.mida.dms.knw.entity.vo.KnwNoumenonVo>> result = null;
        try {
            result = knwNoumenonApi.findAll(search);
            List<com.mida.dms.knw.entity.vo.KnwNoumenonVo> data = result.getData();
            List<Long> collect = data.stream().filter(e -> ObjectUtils.isNotEmpty(e)).map(k -> k.getNoumenonSubType()).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(collect)) {
                Map<Long, String> dataSetNameMap = detailCodingSystemService.getDataSetNameMap(collect);
                if (MapUtils.isNotEmpty(dataSetNameMap)) {
                    data.forEach(k -> k.setNoumenonSubTypeName(dataSetNameMap.get(k.getNoumenonSubType())));
                }
            }

        } catch (Exception e) {
            log.error("查询所有概念域发送异常", e);
            buildListWarn(result, "查询所有概念域失败");
        }
        return result;
    }

    @Override
    public ListResult<List<KnwNoumenonFirstLevelTree>> getTree() {
        log.info("开始本体类型树状结构查询");
        StopWatch stopWatch = StopWatch.createStarted();
        ListResult result = new ListResult();
        try {
            ListResult<List<KnwNoumenonTreeVo>> data = knwNoumenonApi.getTree();
            if (ObjectUtils.isEmpty(data) && CollectionUtils.isEmpty(data.getData())) {
                buildListWarn(result, "本体类型树状结构为空");
                return result;
            }
            List<KnwNoumenonTreeVo> tree = data.getData();
            List<Long> collect = tree.stream().filter(e -> ObjectUtils.isNotEmpty(e)).map(k -> k.getFirstLevelTypeCode()).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(collect)) {
                Map<Long, String> dataSetNameMap = detailCodingSystemService.getDataSetNameMap(collect);
                if (MapUtils.isNotEmpty(dataSetNameMap)) {
                    tree.forEach(k -> k.setFirstLevelTypeName(dataSetNameMap.get(k.getFirstLevelTypeCode())));
                }
            }

            List<Long> collect1 = tree.stream().filter(e -> ObjectUtils.isNotEmpty(e)).map(k -> k.getSecondLevelTypeCode()).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(collect1)) {
                Map<Long, String> dataSetNameMap = detailCodingSystemService.getDataSetNameMap(collect1);
                if (MapUtils.isNotEmpty(dataSetNameMap)) {
                    tree.forEach(k -> k.setSecondLevelTypeName(dataSetNameMap.get(k.getSecondLevelTypeCode())));
                }
            }

            List<KnwNoumenonFirstLevelTree> firstLevelTree = new ArrayList<>(0);
            if (CollectionUtils.isNotEmpty(tree)) {
                firstLevelTree = tree.stream().map(e -> {
                    KnwNoumenonFirstLevelTree first = new KnwNoumenonFirstLevelTree();
                    first.setCode(e.getFirstLevelTypeCode());
                    first.setValue(e.getFirstLevelTypeName());
                    return first;
                }).distinct().collect(Collectors.toList());

                if (CollectionUtils.isNotEmpty(firstLevelTree)) {
                    firstLevelTree.forEach(e -> {
                        List<KnwNoumenonSecondLevelTree> secondLevelTree = tree.stream().filter(t -> (t.getFirstLevelTypeCode().compareTo(e.getCode()) == 0)).distinct().map(m -> {
                            KnwNoumenonSecondLevelTree second = new KnwNoumenonSecondLevelTree();
                            second.setCode(m.getSecondLevelTypeCode());
                            second.setValue(m.getSecondLevelTypeName());
                            return second;
                        }).collect(Collectors.toList());
                        e.setChildren(secondLevelTree);
                    });
                }
            }
            buildListSuccess(result, firstLevelTree);
        } catch (Exception e) {
            log.error("查询本体类型树状结构发送异常", e);
            buildListWarn(result, "查询本体类型树状结构失败");
        } finally {
            stopWatch.stop();
            log.info("本次查询本体类型树状结构耗时:" + stopWatch.getTime() + "ms");
        }
        return result;

    }

    @Override
    public ListResult<List<PullDownMenuVO>> getSubTree(Long noumenonSoid) {
        log.info("开始本体树(局部解剖学)子树查询");
        StopWatch stopWatch = StopWatch.createStarted();
        ListResult result = new ListResult();
        List<PullDownMenuVO> subTree = new ArrayList<PullDownMenuVO>(0);
        try {
            ListResult<List<KnwNoumenonRelationVo>> apiResult = knwNoumenonApi.getSubTree(noumenonSoid);
            if (ObjectUtils.isNotEmpty(apiResult)) {
                List<KnwNoumenonRelationVo> data = apiResult.getData();
                if (CollectionUtils.isNotEmpty(data)) {
                    List<Long> sourceCollect = data.stream().filter(e -> ObjectUtils.isNotEmpty(e)).map(k -> k.getSourceNoumenonSubType()).collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(sourceCollect)) {
                        Map<Long, String> map = detailCodingSystemService.getDataSetNameMap(sourceCollect);
                        if (MapUtils.isNotEmpty(map)) {
                            data.forEach(k -> k.setSourceNoumenonSubTypeName(map.get(k.getSourceNoumenonSubType())));
                        }
                    }

                    List<Long> targetCollect = data.stream().filter(e -> ObjectUtils.isNotEmpty(e)).map(k -> k.getTargetNoumenonSubType()).collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(targetCollect)) {
                        Map<Long, String> map = detailCodingSystemService.getDataSetNameMap(targetCollect);
                        if (MapUtils.isNotEmpty(map)) {
                            data.forEach(k -> k.setTargetNoumenonSubTypeName(map.get(k.getTargetNoumenonSubType())));
                        }
                    }

                    List<PullDownMenuVO> collect = data.stream().map(m -> {
                        PullDownMenuVO vo = new PullDownMenuVO();
                        vo.setCode(m.getSourceNoumenonSoid());
                        vo.setValue(m.getSourceNoumenonName());
                        return vo;
                    }).collect(Collectors.toList());
                    subTree = collect;
                    buildListSuccess(result, subTree);
                } else {
                    buildListSuccess(result, new ArrayList<>(0));
                }
            } else {
                buildListSuccess(result, new ArrayList<>(0));
            }
        } catch (Exception e) {
            log.error("查询本体树子树结构发送异常", e);
            buildListWarn(result, "查询本体类型树状结构失败");
        } finally {
            stopWatch.stop();
            log.info("本次查询本体树子树结构耗时:" + stopWatch.getTime() + "ms");
        }
        return result;
    }

    @Override
    public ActionResult bulkInsertknwNoumenonUserSpace(KnwNoumenonUserSpaceBatchVo knwNoumenonUserSpaceBatchVo) {
        ActionResult actionResult = new ActionResult();

        ListResult<UserDto> userDtoresult = mdmService.getLoginUserInfo();
        UserDto user = userDtoresult.getData();
        if (ObjectUtils.isEmpty(user)) {
            buildActionWarn(actionResult, "人的信息为空");
            return actionResult;
        }

        // 没全选场合
        if (!knwNoumenonUserSpaceBatchVo.getIsSeletcAll() &&
                knwNoumenonUserSpaceBatchVo.getListKnwNoumenonUserSpace() != null &&
                knwNoumenonUserSpaceBatchVo.getListKnwNoumenonUserSpace().size() > 0) {
            knwNoumenonUserSpaceBatchVo.getListKnwNoumenonUserSpace().stream().forEach(vo ->
                    vo.setUpdateUser(user.getEmployeeSoid())
            );

            knwNoumenonApi.bulkInsertknwNoumenonUserSpace(knwNoumenonUserSpaceBatchVo.getListKnwNoumenonUserSpace());
            buildActionSuccess(actionResult);
            return actionResult;
        }

        // 全选的场合、授权空间soid不能为空
        if (knwNoumenonUserSpaceBatchVo.getUseSpaceSoid() == null) {
            actionResult.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            actionResult.setMessage("授权空间的标识不能为空");
            return actionResult;
        }


        KnwNoumenonPageVo vo = new KnwNoumenonPageVo();
        List<String> list = new ArrayList<>();
        list.add(String.valueOf(knwNoumenonUserSpaceBatchVo.getUseSpaceSoid()));
        vo.setUseSpaceSoids(list);
        // 根据授权空间soid、查询当前授权空间未被授权的本体列表
        ListResult<List<com.mida.dms.knw.entity.vo.KnwNoumenonVo>> listTmp = knwNoumenonApi.selectKnwNoumenonVoList(vo);
        List<KnwNoumenonUserSpace> listKnwNoumenonUserSpace = new ArrayList<KnwNoumenonUserSpace>();
        KnwNoumenonUserSpace knwNoumenonUserSpace;
        if (listTmp != null
                && listTmp.getData() != null
                && listTmp.getData().size() > 0) {
            List<com.mida.dms.knw.entity.vo.KnwNoumenonVo> listKnwNoumenonVo = listTmp.getData();
            for (com.mida.dms.knw.entity.vo.KnwNoumenonVo k :listKnwNoumenonVo) {
                knwNoumenonUserSpace = new KnwNoumenonUserSpace();
                knwNoumenonUserSpace.setUpdateUser(user.getEmployeeSoid());
                knwNoumenonUserSpace.setNoumenonSoid(k.getNoumenonSoid());
                knwNoumenonUserSpace.setUseSpaceSoid(knwNoumenonUserSpaceBatchVo.getUseSpaceSoid());
                listKnwNoumenonUserSpace.add(knwNoumenonUserSpace);
            }

            knwNoumenonApi.bulkInsertknwNoumenonUserSpace(listKnwNoumenonUserSpace);
            buildActionSuccess(actionResult);
        } else {
            actionResult.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            actionResult.setMessage("本体列表为空");
        }
        return actionResult;
    }

    @Override
    public ListResult<List<PullDownMenuVO>> getLocalAnatomyRootTree(Long noumenonSoid) {
        log.info("开始本体树(局部解剖学)根树查询");
        StopWatch stopWatch = StopWatch.createStarted();
        ListResult result = new ListResult();
        try {
            // 给局部解剖学增加树形结构
            if (noumenonSoid.longValue() == 2097L) {
                ListResult<List<KnwNoumenonRelationVo>> apiResult = knwNoumenonApi.getLocalAnatomyRootTree(noumenonSoid);
                if (ObjectUtils.isNotEmpty(apiResult)) {
                    List<KnwNoumenonRelationVo> allRelation = apiResult.getData();
                    if (CollectionUtils.isNotEmpty(allRelation)) {
                        List<Long> sourceCollect = allRelation.stream().filter(e -> ObjectUtils.isNotEmpty(e)).map(k -> k.getSourceNoumenonSubType()).collect(Collectors.toList());
                        if (CollectionUtils.isNotEmpty(sourceCollect)) {
                            Map<Long, String> map = detailCodingSystemService.getDataSetNameMap(sourceCollect);
                            if (MapUtils.isNotEmpty(map)) {
                                allRelation.forEach(k -> k.setSourceNoumenonSubTypeName(map.get(k.getSourceNoumenonSubType())));
                            }
                        }

                        List<Long> targetCollect = allRelation.stream().filter(e -> ObjectUtils.isNotEmpty(e)).map(k -> k.getTargetNoumenonSubType()).collect(Collectors.toList());
                        if (CollectionUtils.isNotEmpty(targetCollect)) {
                            Map<Long, String> map = detailCodingSystemService.getDataSetNameMap(targetCollect);
                            if (MapUtils.isNotEmpty(map)) {
                                allRelation.forEach(k -> k.setTargetNoumenonSubTypeName(map.get(k.getTargetNoumenonSubType())));
                            }
                        }

                        List<Long> sourceNoumenonSoidList = allRelation.stream().map(s -> s.getSourceNoumenonSoid()).collect(Collectors.toList());
                        List<PullDownMenuVO> collect = allRelation.stream().filter(r -> r.getConceptualSoid().longValue() == 12262697500409856L).filter(r2 -> !sourceNoumenonSoidList.contains(r2.getTargetNoumenonSoid())).map(r3 -> {
                            PullDownMenuVO vo = new PullDownMenuVO();
                            vo.setCode(r3.getTargetNoumenonSoid());
                            vo.setValue(r3.getTargetNoumenonName());
                            return vo;
                        }).distinct().collect(Collectors.toList());
                        buildListSuccess(result, collect);
                    } else {
                        buildListSuccess(result, new ArrayList<>(0));
                    }
                }
            } else {
                buildListSuccess(result, new ArrayList<>(0));
            }
        } catch (Exception e) {
            log.error("查询本体树(局部解剖学)根树发送异常", e);
            buildListWarn(result, "查询本体树(局部解剖学)根树失败");
        } finally {
            stopWatch.stop();
            log.info("本次查询本体树(局部解剖学)根树耗时:" + stopWatch.getTime() + "ms");
        }
        return result;
    }

    @Override
    public ListResult<PageResultVo<com.mida.dms.knw.entity.vo.KnwNoumenonVo>> selectKnwNoumenonVos(KnwNoumenonPageVo vo) {
        ListResult result = new ListResult<>();
        if (ObjectUtils.isEmpty(vo)) {
            buildListWarn(result, "批量插入本体与授权空间列表不能为空");
            return result;
        }
        if(ObjectUtils.isEmpty(vo.getUseSpaceSoids())){
            buildListWarn(result, "授权空间标识不能为空");
            return result;
        }

        //批量插入查询
        ListResult<PageResultVo<com.mida.dms.knw.entity.vo.KnwNoumenonVo>> page = null;
        page = knwNoumenonApi.selectKnwNoumenonVos(vo);

        PageResultVo<com.mida.dms.knw.entity.vo.KnwNoumenonVo> data = page.getData();
        if (data != null && data.getList() != null && data.getList().size() > 0) {
            List<com.mida.dms.knw.entity.vo.KnwNoumenonVo> list = data.getList();
            List<Long> noumenonTypes = list.stream().filter(e -> ObjectUtils.isNotEmpty(e.getNoumenonType())).map(knwNoumenonVo -> knwNoumenonVo.getNoumenonType()).collect(Collectors.toList());
            List<Long> noumenonSubTypes = list.stream().filter(e -> ObjectUtils.isNotEmpty(e.getNoumenonSubType())).map(knwNoumenonVo -> knwNoumenonVo.getNoumenonSubType()).collect(Collectors.toList());
            Map<Long, String> dataSetNameMap = detailCodingSystemService.getDataSetNameMap(noumenonTypes);
            Map<Long, String> dataSetNameMapSub = detailCodingSystemService.getDataSetNameMap(noumenonSubTypes);
            list.stream().filter(knwNoumenonVo -> ObjectUtils.isNotEmpty(knwNoumenonVo)).forEach(knwNoumenonVo -> {
                String dataSetMeaning = dataSetNameMap.get(knwNoumenonVo.getNoumenonType());
                String dataSetMeaningSub = dataSetNameMapSub.get(knwNoumenonVo.getNoumenonSubType());
                knwNoumenonVo.setNoumenonTypeName(dataSetMeaning);
                knwNoumenonVo.setNoumenonSubTypeName(dataSetMeaningSub);
                knwNoumenonVo.setPageTypeName(dataSetMeaning + "|" + dataSetMeaningSub);
            });

        }

        //批量插入查询
        return page;
    }
}
